/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.cvut.fel.taskpro.data.manager;


import cz.cvut.fel.taskpro.data.entity.Assignment;
import cz.cvut.fel.taskpro.data.entity.GroupTaskPro;
import cz.cvut.fel.taskpro.data.entity.Kantor;
import cz.cvut.fel.taskpro.data.entity.Student;
import cz.cvut.fel.taskpro.data.entity.Team;
import cz.cvut.fel.taskpro.data.imanager.ITeamData;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Subquery;

/**
 * This class implement #{@link ITeamData} interface
 * @author Tom
 * @version 1.0. beta
 */
@Stateless
public class TeamData extends ObjectManager implements ITeamData {

    @Override
    public void addTeam(Team teamToAdd) {
        for (Student student : teamToAdd.getmStudents()) {
            student.addTeam(teamToAdd);
            super.update(student);
        }
        super.add(teamToAdd);
    }

    @Override
    public void removeTeam(Team teamToRemove) {
        super.remove(teamToRemove);
    }

    @Override
    public List<Team> getTeamByKantor(Kantor kantor) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Team> queryTeam = cb.createQuery(Team.class);
        Root<Team> queryTeamRoot = queryTeam.from(Team.class);
        Join<GroupTaskPro, Team> groupTeam = queryTeamRoot.join("group");
        Predicate kantorGroup = cb.equal(groupTeam.get("kantor"), kantor);
        queryTeam.where(kantorGroup).distinct(true).orderBy(cb.asc(queryTeamRoot.get("name")));
        TypedQuery typedQuery = em.createQuery(queryTeam);
        List<Team> resultList = typedQuery.getResultList();
        return resultList;
    }

    @Override
    public List<Team> getTeamByGroup(List<GroupTaskPro> groups) {
        List<Team> teams = new ArrayList<Team>();
        Iterator it = groups.iterator();
        Query teamQ = em.createNamedQuery("Team.FindByGroup");
        while (it.hasNext()) {
            GroupTaskPro currGroupTaskPro = (GroupTaskPro) it.next();
            teamQ.setParameter("group", currGroupTaskPro);
            teams.addAll(teamQ.getResultList());
        }
        return teams;
    }

    @Override
    public List<Student> getStudentsInTeamByGroup(GroupTaskPro group) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Student> queryStudent = cb.createQuery(Student.class);
        Root<Student> queryStudentRoot = queryStudent.from(Student.class);
        Join<Student, Team> stundentTeam = queryStudentRoot.join("team");
        Join<Team, GroupTaskPro> groupTeam = stundentTeam.join("group");
        Predicate groupPredicate = cb.equal(groupTeam, group);
        queryStudent.where(groupPredicate).orderBy(cb.asc(queryStudentRoot.get("login")));
        TypedQuery typedQuery = em.createQuery(queryStudent);
        List<Student> mStudents = typedQuery.getResultList();
        return mStudents;
    }

    @Override
    public List<Team> getTeamByContext(String teamName, GroupTaskPro group) {
        CriteriaBuilder cb = em.getCriteriaBuilder();   
        CriteriaQuery<Team> queryTeam = cb.createQuery(Team.class);
        Root<Team> queryTeamRoot = queryTeam.from(Team.class);
        Predicate teamNamePredicate = cb.equal(queryTeamRoot.get("name"), teamName);
        Predicate teamGroupPredicate = cb.equal(queryTeamRoot.get("group"), group);
        queryTeam.where(cb.and(teamNamePredicate, teamGroupPredicate));
        queryTeam.orderBy(cb.asc(queryTeamRoot.get("name")));
        TypedQuery typedQuery = em.createQuery(queryTeam);
        List<Team> teams = typedQuery.getResultList();
        return teams;
    }

    @Override
    public List<Team> getTeamsByStudent(Student student) {

        throw new UnsupportedOperationException("Not supported yet.");
    }

    public List<Team> getTeamOnAssingmentSubmit(Assignment assignment, Student memberOfTeam) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Team> queryTeam = cb.createQuery(Team.class);
        Root<Team> queryTeamRoot = queryTeam.from(Team.class);
        Subquery assingmentQuery = queryTeam.subquery(Assignment.class);
        Root aRoot = assingmentQuery.from(Assignment.class);
        Join<Assignment, Team> asT = aRoot.join("mTeams");
        Predicate isMember = cb.equal(asT.get("mStudents"), memberOfTeam);
        assingmentQuery.select(aRoot);
        assingmentQuery.where(isMember);
        queryTeam.where(cb.exists(assingmentQuery));
        queryTeam.orderBy(cb.asc(queryTeamRoot.get("name")));
        queryTeam.distinct(true);
        TypedQuery typedQuery = em.createQuery(queryTeam);
        List<Team> resultList = typedQuery.getResultList();
        return resultList;
    }

    @Override
    public void updateTeam(Team teamToUpdate) {
        super.update(teamToUpdate);
    }

    @Override
    public Team getTeamByStudentAndGroup(Student studentInTeam, GroupTaskPro group) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Team> queryTeam = cb.createQuery(Team.class);
        Root<Team> rootQueryTeam = queryTeam.from(Team.class);
        Predicate studentPredicate = cb.equal(rootQueryTeam.get("mStudents"), studentInTeam);
        Predicate groupPredicate = cb.equal(rootQueryTeam.get("group"), group);
        queryTeam.where(cb.and(studentPredicate, groupPredicate)).orderBy(cb.asc(rootQueryTeam.get("name")));
        TypedQuery typedQuery = em.createQuery(queryTeam);
        List<Team> resultList = typedQuery.getResultList();
        if (resultList.isEmpty()) {
            return null;
        } else {
            return resultList.get(0);
        }
    }
}
